package com.ruoyi.performance.service.impl;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.ruoyi.performance.mapper.PerfCheckMapper;
import com.ruoyi.performance.mapper.PerfCheckreportMapper;
import com.ruoyi.performance.mapper.PerfCheckresultMapper;
import com.ruoyi.performance.domain.PerfCheck;
import com.ruoyi.performance.domain.PerfCheckreport;
import com.ruoyi.performance.domain.PerfCheckresult;
import com.ruoyi.performance.service.IPerfCheckService;

import lombok.extern.slf4j.Slf4j;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Joiner;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;

/**
 * 绩效考核管理Service业务层处理
 * 
 * @author ygx
 * @date 2020-08-31
 */
@Service
@Slf4j
public class PerfCheckServiceImpl implements IPerfCheckService {
	@Autowired
	private PerfCheckMapper perfCheckMapper;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	@Autowired
	private PerfCheckresultMapper perfCheckresultMapper;
	@Autowired
	PerfCheckreportMapper perfCheckreportMapper;

	// 新增
	final static String New = "New";
	// 作业中
	final static String Process = "Process";
	// 作业完成
	final static String WorkFinish = "WorkFinish";
	// 拒绝
	final static String Reject = "Reject";
	// 考核完成并生成考核单
	final static String Finish = "Finish";
	// 取消
	final static String Cancel = "Cancel";
	// 删除
	final static String Delete = "Delete";

	/**
	 * 查询绩效考核管理
	 * 
	 * @param perfcheckId 绩效考核管理ID
	 * @return 绩效考核管理
	 */
	@Override
	public List<PerfCheck> selectPerfCheckById(Long perfcheckId) {
		return perfCheckMapper.selectPerfCheckById(perfcheckId);
	}

	/**
	 * 查询绩效考核管理列表
	 * 
	 * @param perfCheck 绩效考核管理
	 * @return 绩效考核管理
	 */
	@Override
	public List<PerfCheck> selectPerfCheckList(PerfCheck perfCheck) {
		// 拆分状态字符串
		List<String> statuslist = perfCheck.getStatuslist();
		if (statuslist != null && statuslist.size() > 0) {
			String status = "'" + StringUtils.join(statuslist, "','") + "'";
			perfCheck.setStatus(status);
		}
		String createdate = perfCheck.getCreatedate();
		if (createdate != null && StringUtils.isNotBlank(createdate))
		{
			perfCheck.setCreatedate(new SimpleDateFormat("yyyymmdd").format(createdate));
		}
		return perfCheckMapper.selectPerfCheckList(perfCheck);
	}

	/**
	 * 绩效打分列表(新srm，拼接结果)
	 * 
	 * @param perfCheckresult 绩效打分
	 * @return 绩效打分
	 */
	@Override
	public List<Map<String, Object>> selectResultList(PerfCheck perfCheck) {
		HttpServletRequest request = ServletUtils.getRequest();
		String userId = request.getHeader(Constants.CURRENT_ID);
		perfCheck.setUserId(Long.valueOf(userId));
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		// 拆分状态字符串
		List<String> statuslist = perfCheck.getStatuslist();
		if (statuslist != null && statuslist.size() > 0) {
			String status = "'" + StringUtils.join(statuslist, "','") + "'";
			perfCheck.setStatus(status);
		}
		List<PerfCheck> checkLists = perfCheckMapper.selectResultList(perfCheck);
		for (PerfCheck checkList : checkLists) {
			@SuppressWarnings("unchecked")
			//对象转字符串
			Map<String, Object> resultmap = JSON.parseObject(JSON.toJSONString(checkList), Map.class);
			List<PerfCheckresult> resultlist = perfCheckresultMapper.selectResultList(Long.valueOf(userId),
					checkList.getCheckcode());
			resultmap.put("templateArray", resultlist);
			result.add(resultmap);
		}
		return result;
	}

	/**
	 * 查询绩效打分列表all(新srm，拼接结果)
	 * 
	 * @param perfCheckresult 绩效打分
	 * @return 绩效打分
	 */
	@Override
	public List<Map<String, Object>> selectResultListAll(PerfCheck perfCheck) {
		HttpServletRequest request = ServletUtils.getRequest();
		String userId = request.getHeader(Constants.CURRENT_ID);
		perfCheck.setUserId(Long.valueOf(userId));
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<PerfCheck> checkLists = perfCheckMapper.selectResultListAll(perfCheck);
		for (PerfCheck checkList : checkLists) {
			@SuppressWarnings("unchecked")
			Map<String, Object> resultmap = JSON.parseObject(JSON.toJSONString(checkList), Map.class);
			List<PerfCheckresult> resultlist = perfCheckresultMapper.selectResultListAll(Long.valueOf(userId),
					checkList.getCheckcode());
			resultmap.put("templateArray", resultlist);
			result.add(resultmap);
		}
		return result;
	}

	/**
	 * 新增绩效考核管理
	 * 
	 * @param perfCheck绩效考核管理
	 * @return 结果
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String insertPerfCheck(Map<String, List<PerfCheck>> datas) {
		String result = "1";
		List<String> check = new ArrayList<String>();
		HttpServletRequest request = ServletUtils.getRequest();
		String username = request.getHeader(Constants.CURRENT_USERNAME);
		String datedate = new SimpleDateFormat("yyyyMMdd").format(new Date());
		String datetime = new SimpleDateFormat("HHmmss").format(new Date());
		List<PerfCheck> perfChecks = datas.get("datas");
		for (PerfCheck perfCheck : perfChecks) {
			String checkUnique = perfCheckMapper.checkUnique(perfCheck);
			if (StringUtils.isBlank(checkUnique) && checkUnique != null) {
				check.add(checkUnique + "考核单在同一归属年，同一归属月，同一考核类型存在" + "供应商" + perfCheck.getVendorname() + "编号"
						+ perfCheck.getVendorcode() + "，  不允许重复新增！");
			} else {
				perfCheck.setCheckcode(createContractCode(perfCheck.getCompanycode(), "VPC"));
				perfCheck.setCreateuser(username);
				perfCheck.setCreatedate(datedate);
				perfCheck.setCreatetime(Long.valueOf(datetime));
				perfCheck.setStatus("New");
				try {
					perfCheckMapper.insertPerfCheck(perfCheck);
				} catch (Exception e) {
					result = "新增考核单" + perfCheck.getCheckcode() + "失败,请联系管理员！";
					log.error(result, e);
					TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
					return result;
				}
			}
		}
		if (check.size() > 0 && check != null) {
			result = Joiner.on(",").join(check);
		}
		return result;
	}

	/**
	 * 修改绩效考核管理
	 * 
	 * @param perfCheck 绩效考核管理
	 * @return 结果
	 */
	@Override

	public int updatePerfCheck(PerfCheck perfCheck) {
		HttpServletRequest request = ServletUtils.getRequest();
		String username = request.getHeader(Constants.CURRENT_USERNAME);
		String datedate = new SimpleDateFormat("yyyyMMdd").format(new Date());
		String datetime = new SimpleDateFormat("HHmmss").format(new Date());
		perfCheck.setLogdate(Long.valueOf(datedate));
		perfCheck.setLogtime(Long.valueOf(datetime));
		perfCheck.setLoguser(username);
		return perfCheckMapper.updatePerfCheck(perfCheck);
	}

	/**
	 * 修改绩效考核单状态
	 * 
	 * @param perfCheck 绩效考核管理
	 * @return 结果
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String updatePerfStatus(Map<String, List<PerfCheck>> datas) {

		String result = "1";
		List<String> checkstatus = new ArrayList<String>();
		HttpServletRequest request = ServletUtils.getRequest();
		String username = request.getHeader(Constants.CURRENT_USERNAME);
		String userId = request.getHeader(Constants.CURRENT_ID);
		String datedate = new SimpleDateFormat("yyyyMMdd").format(new Date());
		String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
		String datetime = new SimpleDateFormat("HHmmss").format(new Date());

		for (PerfCheck perfCheck : datas.get("datas")) {
			String checkcode = perfCheck.getCheckcode();
			perfCheck.setLogdate(Long.valueOf(datedate));
			perfCheck.setLogtime(Long.valueOf(datetime));
			perfCheck.setLoguser(username);
			result = checkstatus(perfCheck.getPerfcheckId(), perfCheck.getStatus(), checkcode);
			if (result == "1") {

				if (Process.equals(perfCheck.getStatus())) {
					// 启动作业时，将数据插入打分表
					PerfCheckresult perfCheckresult = new PerfCheckresult();
					perfCheckresult.setCreatedate(Long.valueOf(datedate));
					perfCheckresult.setCreatetime(Long.valueOf(datetime));
					perfCheckresult.setCreateuser(username);
					perfCheckresult.setCheckcode(checkcode);
					String startdate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
					perfCheck.setStartdate(startdate);
					int workday = perfCheckMapper.selectWorkDays(checkcode);
                    Date nowdate=new Date();//取时间
		            Calendar calendar = new GregorianCalendar();
		            calendar.setTime(nowdate);
		            //启动时间（当前时间）加计划考核时间等于计划完成时间
		            calendar.add(Calendar.DATE,workday);//把日期往后增加n天，若想把日期向前减少n天则将正数改为负数
					String planenddate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
					perfCheck.setPlanenddate(planenddate);
					try {
						perfCheckresultMapper.insertreSultFromCheck(perfCheckresult);
					} catch (Exception e) {
						result = checkcode + "数据写入打分表失败，请联系管理员！";
						log.error(result, e);
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
						return result;
					}
					
					try {
						perfCheckMapper.updatePerfStatus(perfCheck);
					} catch (Exception e) {
						result = checkcode + "更改状态失败，请联系管理员！";
						log.error(result, e);
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
						return result;
					}
				}
				if (WorkFinish.equals(perfCheck.getStatus())) {
					perfCheck.setUserId(Long.valueOf(userId));
					String actualenddate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
					perfCheck.setActualenddate(actualenddate);
					try {
						// 责任人提交作业时，将打分表涉及的细项状态改为public
						perfCheckMapper.updateResultStatus(perfCheck);
					} catch (Exception e) {
						result = checkcode + "修改打分表状态，请联系管理员！";
						log.error(result, e);
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
						return result;
					}
					// 判断该考核单打分表是否存在new状态的数据
					if (!perfCheckresultMapper.selectResultStatus(checkcode)) {
						// 该考核单全部打分表涉及的细项状态都为public，提交作业时，将总分与绩效等级写入考核报告表
						Long sumscore = perfCheckresultMapper.getSumScore(checkcode);
						String levle = getlevelResult(sumscore, checkcode);
						if (StringUtils.contains(levle, "管理员")) {
							TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
							return levle;
						}
						String checkreportcode = createContractCode(perfCheck.getCompanycode(), "VPR");
						PerfCheckreport perfCheckreport = new PerfCheckreport();
						perfCheckreport.setFirstscore(sumscore);
						perfCheckreport.setFirstlevel(levle);
						perfCheckreport.setCheckcode(checkcode);
						perfCheckreport.setFirstusername(username);
						perfCheckreport.setFirstdate(date);
						perfCheckreport.setCheckreportcode(checkreportcode);
						try {
							perfCheckreportMapper.insertReport(perfCheckreport);
						} catch (Exception e) {
							result = checkcode + "绩效报告单生成失败，请联系管理员！";
							log.error(result, e);
							TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
							return result;
						}
						
						try {
							perfCheckMapper.updatePerfStatus(perfCheck);
						} catch (Exception e) {
							result = checkcode + "更改状态失败，请联系管理员！";
							log.error(result, e);
							TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
							return result;
						}
					}
					else
					{
						perfCheck.setStatus("Process");
					}
				}
				//取消的除将考核报告单号清空外，还需要将打分表、报告单表内容删除
			} else {
				checkstatus.add(result);
			}

		}
	
		if (checkstatus.size() > 0 && checkstatus != null) {
			result = Joiner.on(",").join(checkstatus);
		}
		return result;
	}

	/**
	 * 删除绩效考核管理对象
	 * 
	 * @param ids 需要删除的数据ID
	 * @return 结果
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String deletePerfCheckByIds(String ids) {
		String result = "1";
		List<String> checkstatus = new ArrayList<String>();
		String[] id = ids.split(",");
		for (String perfcheckId : id) {
			Long perfcheckIdL = Long.valueOf(perfcheckId);
			result = checkstatus(perfcheckIdL, "Delete", perfCheckMapper.selectCodeById(perfcheckIdL));
			if (result == "1") {
				try {
					perfCheckMapper.deletePerfCheckById(Long.valueOf(perfcheckIdL));
				} catch (Exception e) {
					result = "删除考核单失败,考核单Id" + perfcheckIdL + ",请联系管理员！";
					log.error(result, e);
					TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
					return result;
				}
			} else {
				checkstatus.add(result);
			}
		}
		if (checkstatus.size() > 0 && checkstatus != null) {
			result = Joiner.on(",").join(checkstatus);
		}
		return result;
	}

	/**
	 * 删除绩效考核管理信息
	 * 
	 * @param perfcheckId 绩效考核管理ID
	 * @return 结果
	 */
	public int deletePerfCheckById(Long perfcheckId) {
		return perfCheckMapper.deletePerfCheckById(perfcheckId);
	}

	/**
	 * 通过redis自增生成考核单号（如：HTBJ202008030001）
	 * 
	 * @param prefix 合同号前缀 companycode 公司code factoryType 公司别名
	 * @return 合同号
	 */
	public String createContractCode(String companycode, String prefix) {
		String factoryType = perfCheckMapper.selectFactoryType(companycode);
		String datetime = new SimpleDateFormat("yyyyMMdd").format(new Date());
		String key = prefix + factoryType + datetime;

		// 查询 key 是否存在， 不存在返回 1 ，存在的话则自增加1
		Long autoID = redisTemplate.opsForValue().increment(key, 1);
		// 这里是 4 位id，如果位数不够可以自行修改 ，下面的意思是 得到上面 key 的 值，位数为 4 ，不够的话在左边补 0 ，比如 110 会变成
		// 0110
		String value = StringUtils.leftPad(String.valueOf(autoID), 4, "0");
		// 然后把 时间戳和优化后的 ID 拼接
		String code = MessageFormat.format("{0}{1}", key, value);
		// 设置三天过期
		redisTemplate.expire(key, 3, TimeUnit.DAYS);
		return code;
	}

	/**
	 * 根据考核单号查询考核单状态
	 * 
	 * @param perfcheckId
	 * @return 是否允许变更考核单状态
	 */
	public String checkstatus(Long perfcheckId, String status, String checkcode) {
		String s = perfCheckMapper.selectStatusById(perfcheckId);
		if (Process.equals(status)) {
			if (!New.equals(s))
			{
				return checkcode + "启动失败，只有状态为新增的考核单才能启动！";
			}
			List<Map<String, String>> checkGroupDitems = perfCheckMapper.checkGroupDitem(checkcode);
			if (checkGroupDitems.size() > 0 && checkGroupDitems !=null)
			{
				for (Map<String, String> checkGroupDitem : checkGroupDitems)
				{
					String ditemcode = checkGroupDitem.get("ditem_code");
					if (StringUtils.isBlank(ditemcode) && ditemcode == null)
					{
						return "1";
					}
					String templatecode = checkGroupDitem.get("templatecode");
					return "考核单" + checkcode + "发布失败：" + "考核模板" + templatecode + "下的明细" + ditemcode + "未绑定打分人！请绑定后重新发布！";
				}
				
			}
			else
			{
				return "未找到" + checkcode + "绑定的考核模板,启动失败！";
			}
			return "1";
			
		} else if (Delete.equals(status) && !New.equals(s)) {
			return checkcode + "删除失败，只能删除新增或取消状态的考核单！";
		} else if (WorkFinish.equals(status) && !Process.equals(s)) {
			return checkcode + "提交失败，只能提交作业中的考核单！";
		} else if (Finish.equals(status) && !Finish.equals(s)) {
			return checkcode + "生成报告失败，只有作业完成的考核单才能生成考核报告！";
		} else if (Reject.equals(status) && !Process.equals(s)) {
			return checkcode + "拒绝失败，只能拒绝作业中的考核单！";
		} else {
			return "1";
		}
	}

	/**
	 * 根据总分、考核单号获取考核等级
	 * 
	 * @param sumscore
	 * @param checkcode
	 * @return
	 */
	public String getlevelResult(Long sumscore, String checkcode) {
		String level = null;
		if (sumscore < 0)
		{
			sumscore = 0L;
		}
		if (sumscore > 100)
		{
			sumscore = 100L;
		}
		//通过考核单号获取改考核对应的打分等级模板
		List<PerfCheckresult> results = perfCheckresultMapper.getLevel(checkcode);
		for (PerfCheckresult result : results) {
			if (sumscore >= Long.valueOf(result.getLowerscore()) && sumscore <= Long.valueOf(result.getUpperscore())) {
				level = result.getLevelcode();
				if (StringUtils.isBlank(level) || level == null) {
					String error = "考核单" + checkcode + "总分为" + sumscore + "无该分值对应的绩效等级，请联系管理员！";
					log.error(error);
					return error;
				}
				{
					return level;
				}
			}
		}
		String error = "考核单" + checkcode + "总分为" + sumscore + "无该分值对应的分值区间，请联系管理员！";
		log.error(error);
		return error;
	}
}
